bitkeeper revision 1.372 (3f1d3b4c5vpfm6WgqbVfZVhO04znVw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 22 Jul 2003 13:25:32 +0000 (13:25 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 22 Jul 2003 13:25:32 +0000 (13:25 +0000)
time.h, keyhandler.c, ac_timer.c, time.c, nmi.c, apic.c:
  Clean ups.

xen/arch/i386/apic.c
xen/arch/i386/nmi.c
xen/arch/i386/time.c
xen/common/ac_timer.c
xen/common/keyhandler.c
xen/include/asm-i386/time.h

index 7710eaa8036501a65ea7b8f9ed1accafbbdae261..ad17799601589ae373d15d5370150d39c77ae539 100644 (file)
@@ -581,7 +581,7 @@ int __init calibrate_APIC_clock(void)
     int i;
     const int LOOPS = HZ/10;
 
-    printk("calibrating APIC timer for CPU%d...\n",  smp_processor_id());
+    printk("Calibrating APIC timer for CPU%d...\n",  smp_processor_id());
 
     /* Put whatever arbitrary (but long enough) timeout
      * value into the APIC clock, we just want to get the
@@ -611,12 +611,12 @@ int __init calibrate_APIC_clock(void)
     result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
 
     printk("..... CPU speed is %ld.%04ld MHz.\n",
-           ((long)(t2-t1)/LOOPS)/(1000000/HZ),
-           ((long)(t2-t1)/LOOPS)%(1000000/HZ));
+           ((long)(t2-t1)/LOOPS) / (1000000/HZ), 
+           ((long)(t2-t1)/LOOPS) % (1000000/HZ));
 
     printk("..... Bus speed is %ld.%04ld MHz.\n",
-           result/(1000000/HZ),
-           result%(1000000/HZ));
+           result / (1000000/HZ), 
+           result % (1000000/HZ));
 
     cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
 
@@ -625,10 +625,7 @@ int __init calibrate_APIC_clock(void)
     bus_cycle  = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
     bus_scale  = (1000*262144)/bus_cycle;
 
-    /* print results */
-    printk("..... bus_freq  = %u Hz\n",  bus_freq);
-    printk("..... bus_cycle = %u ps\n",  bus_cycle);
-    printk("..... bus_scale = %u \n",    bus_scale);
+    printk("..... bus_scale = 0x%08X\n", bus_scale);
     /* reset APIC to zero timeout value */
     __setup_APIC_LVTT(0);
     return result;
index 7062e5686535a455583a70f1baf21d1a1fb84eab..7b338a98d9684c8c52d32c451396283c98561900 100644 (file)
@@ -93,29 +93,33 @@ int __init check_nmi_watchdog (void)
     unsigned int prev_nmi_count[NR_CPUS];
     int j, cpu;
     
-    if (!nmi_watchdog)
+    if ( !nmi_watchdog )
         return 0;
 
-    printk("testing NMI watchdog ---\n");
+    printk("Testing NMI watchdog --- ");
 
-    for (j = 0; j < smp_num_cpus; j++) {
+    for ( j = 0; j < smp_num_cpus; j++ ) 
+    {
         cpu = cpu_logical_map(j);
         prev_nmi_count[cpu] = irq_stat[cpu].__nmi_count;
     }
     sti();
     mdelay((10*1000)/nmi_hz); /* wait 10 ticks */
 
-    for (j = 0; j < smp_num_cpus; j++) {
+    for ( j = 0; j < smp_num_cpus; j++ ) 
+    {
         cpu = cpu_logical_map(j);
-        if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5)
-            printk("CPU#%d: NMI stuck?\n", cpu);
+        if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 )
+            printk("CPU#%d stuck. ", cpu);
         else
-            printk("CPU#%d: NMI okay\n", cpu);
+            printk("CPU#%d okay. ", cpu);
     }
 
+    printk("\n");
+
     /* now that we know it works we can reduce NMI frequency to
        something more reasonable; makes a difference in some configs */
-    if (nmi_watchdog == NMI_LOCAL_APIC)
+    if ( nmi_watchdog == NMI_LOCAL_APIC )
         nmi_hz = 1;
 
     return 0;
@@ -132,8 +136,7 @@ static inline void nmi_pm_init(void) { }
 static void __pminit clear_msr_range(unsigned int base, unsigned int n)
 {
     unsigned int i;
-
-    for(i = 0; i < n; ++i)
+    for ( i = 0; i < n; i++ )
         wrmsr(base+i, 0, 0);
 }
 
index b0159250c234633facb4aa9df3354c2d763a54cd..7d34bb409830fa1d3e2e025e228f908abd4c33d0 100644 (file)
@@ -1,22 +1,16 @@
 /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
  ****************************************************************************
- * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2002-2003 University of Cambridge
  ****************************************************************************
  *
  *        File: i386/time.c
- *      Author: 
- *     Changes: 
- *              
- *        Date: Jan 2003
+ *      Author: Rolf Neugebar & Keir Fraser
  * 
  * Environment: Xen Hypervisor
  * Description: modified version of Linux' time.c
  *              implements system and wall clock time.
  *              based on freebsd's implementation.
- *
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
- ****************************************************************************
  */
 
 /*
 #define TRC(_x)
 #endif
 
+/* GLOBALS */
+
 unsigned long cpu_khz;  /* Detected as we calibrate the TSC */
 unsigned long ticks_per_usec; /* TSC ticks per microsecond. */
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+int timer_ack = 0;
 
-/* We use this to prevent overflow of 31-bit RDTSC "diffs". */
-static unsigned int rdtsc_bitshift;
+/* PRIVATE */
 
-spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int    rdtsc_bitshift;  /* Which 32 bits of TSC do we use?   */
+static unsigned long   init_cmos_time;  /* RTC time when system time == 0    */
+static u64             cpu_freqs[3];    /* Slow/correct/fast CPU freqs       */
+static u32             st_scale_f;      /* Cycles -> ns, fractional part     */
+static u32             st_scale_i;      /* Cycles -> ns, integer part        */
+static struct ac_timer update_timer;    /* Periodic 'time update' function   */
+static spinlock_t      stime_lock;      /* Lock for accessing sys & wc time  */
+struct timeval         wall_clock_time; /* WC time at last 'time update'     */
+static u32             tsc_irq;         /* CPU0's TSC at last 'time update'  */
+static s_time_t        stime_irq;       /* System time at last 'time update' */
 
-int timer_ack=0;
-extern spinlock_t i8259A_lock;
-static inline void do_timer_interrupt(int irq, 
-                                      void *dev_id, struct pt_regs *regs)
+/*
+ * The scale update period is not a whole number of seconds since we want to
+ * avoid being in sync with the CMOS update-in-progress flag.
+ */
+#define SCALE_UPDATE_PERIOD MILLISECS(50200)
+#define TIME_UPDATE_PERIOD  MILLISECS(200)
+
+
+static inline void do_timer_interrupt(
+    int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_IO_APIC
-    if (timer_ack) {
+    if ( timer_ack ) 
+    {
         /*
          * Subtle, when I/O APICs are used we have to ack timer IRQ manually 
          * to reset the IRR bit for do_slow_gettimeoffset(). This will also 
          * deassert NMI lines for the watchdog if run on an 82489DX-based 
          * system.
          */
+        extern spinlock_t i8259A_lock;
         spin_lock(&i8259A_lock);
         outb(0x0c, 0x20);
         /* Ack the IRQ; AEOI will end it automatically. */
@@ -102,6 +116,8 @@ static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
 
 static unsigned long __init calibrate_tsc(void)
 {
+    unsigned long startlow, starthigh, endlow, endhigh, count;
+
     /* Set the Gate high, disable speaker */
     outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
@@ -116,44 +132,25 @@ static unsigned long __init calibrate_tsc(void)
     outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
     outb(CALIBRATE_LATCH >> 8, 0x42);   /* MSB of count */
 
-    {
-        unsigned long startlow, starthigh;
-        unsigned long endlow, endhigh;
-        unsigned long count;
-
-        rdtsc(startlow,starthigh);
-        count = 0;
-        do {
-            count++;
-        } while ((inb(0x61) & 0x20) == 0);
-        rdtsc(endlow,endhigh);
-
-        /* Error: ECTCNEVERSET */
-        if (count <= 1)
-            goto bad_ctc;
-
-        /* 64-bit subtract - gcc just messes up with long longs */
-        __asm__("subl %2,%0\n\t"
-                "sbbl %3,%1"
-                :"=a" (endlow), "=d" (endhigh)
-                :"g" (startlow), "g" (starthigh),
-                "0" (endlow), "1" (endhigh));
-
-        /* Error: ECPUTOOFAST */
-        if (endhigh)
-            goto bad_ctc;
-
-        return endlow;
-    }
+    rdtsc(startlow, starthigh);
+    for ( count = 0; (inb(0x61) & 0x20) == 0; count++ )
+        continue;
+    rdtsc(endlow, endhigh);
 
-    /*
-     * The CTC wasn't reliable: we got a hit on the very first read, or the CPU
-     * was so fast/slow that the quotient wouldn't fit in 32 bits..
-     */
- bad_ctc:
-    return 0;
+    /* Error if the CTC doesn't behave itself. */
+    if ( count == 0 )
+        return 0;
+
+    /* [endhigh:endlow] = [endhigh:endlow] - [starthigh:startlow] */
+    __asm__( "subl %2,%0 ; sbbl %3,%1"
+             : "=a" (endlow), "=d" (endhigh)
+             : "g" (startlow), "g" (starthigh), "0" (endlow), "1" (endhigh) );
+
+    /* If quotient doesn't fit in 32 bits then we return error (zero). */
+    return endhigh ? 0 : endlow;
 }
 
+
 /***************************************************************************
  * CMOS Timer functions
  ***************************************************************************/
@@ -178,32 +175,32 @@ mktime (unsigned int year, unsigned int mon,
         unsigned int day, unsigned int hour,
         unsigned int min, unsigned int sec)
 {
-    if (0 >= (int) (mon -= 2)) {   /* 1..12 -> 11,12,1..10 */
-        mon += 12;                 /* Puts Feb last since it has leap day */
+    /* 1..12 -> 11,12,1..10: put Feb last since it has a leap day. */
+    if ( 0 >= (int) (mon -= 2) )
+    {
+        mon += 12;
         year -= 1;
     }
+
     return ((((unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day)+
               year*365 - 719499
         )*24 + hour /* now have hours */
-        )*60 + min /* now have minutes */
+        )*60 + min  /* now have minutes */
         )*60 + sec; /* finally seconds */
 }
 
 static unsigned long __get_cmos_time(void)
 {
     unsigned int year, mon, day, hour, min, sec;
-    /* Linux waits here for a the Update-In-Progress (UIP) flag going
-     * from 1 to 0. This can take up to a second. This is not acceptable
-     * for the use in Xen and this code is therfor removed at the cost
-     * of reduced accuracy. */
-    sec = CMOS_READ(RTC_SECONDS);
-    min = CMOS_READ(RTC_MINUTES);
+
+    sec  = CMOS_READ(RTC_SECONDS);
+    min  = CMOS_READ(RTC_MINUTES);
     hour = CMOS_READ(RTC_HOURS);
-    day = CMOS_READ(RTC_DAY_OF_MONTH);
-    mon = CMOS_READ(RTC_MONTH);
+    day  = CMOS_READ(RTC_DAY_OF_MONTH);
+    mon  = CMOS_READ(RTC_MONTH);
     year = CMOS_READ(RTC_YEAR);
     
-    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+    if ( !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD )
     {
         BCD_TO_BIN(sec);
         BCD_TO_BIN(min);
@@ -213,7 +210,7 @@ static unsigned long __get_cmos_time(void)
         BCD_TO_BIN(year);
     }
 
-    if ((year += 1900) < 1970)
+    if ( (year += 1900) < 1970 )
         year += 100;
 
     return mktime(year, mon, day, hour, min, sec);
@@ -239,42 +236,33 @@ static unsigned long maybe_get_cmos_time(void)
     return retval;
 }
 
-/* the more accurate version waits for a change */
+/* This version spins until it definitely reads a valid time from CMOS RAM. */
 static unsigned long get_cmos_time(void)
 {
     unsigned long res, flags;
     int i;
 
     spin_lock_irqsave(&rtc_lock, flags);
-    /* The Linux interpretation of the CMOS clock register contents:
-     * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-     * RTC registers show the second which has precisely just started.
-     * Let's hope other operating systems interpret the RTC the same way.
-     */
+
     /* read RTC exactly on falling edge of update flag */
-    for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
-        if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+    for ( i = 0 ; i < 1000000 ; i++ ) /* may take up to 1 second... */
+        if ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
             break;
-    for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
-        if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+    for ( i = 0 ; i < 1000000 ; i++ ) /* must try at least 2.228 ms */
+        if ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) )
             break;
+
     res = __get_cmos_time();
+
     spin_unlock_irqrestore(&rtc_lock, flags);
     return res;
 }
 
+
 /***************************************************************************
- * Time
- * XXX RN: Will be able to remove some of the locking once the time is
- * update by the APIC on only one CPU. 
+ * System Time
  ***************************************************************************/
 
-static spinlock_t stime_lock;
-static u32  st_scale_f;
-static u32  st_scale_i;
-u32         stime_pcc;   /* cycle counter value at last timer irq */
-s_time_t    stime_now;   /* time in ns at last timer IRQ */
-
 static inline s_time_t __get_s_time(void)
 {
     s32      delta_tsc;
@@ -283,13 +271,13 @@ static inline s_time_t __get_s_time(void)
     
     rdtscll(tsc);
     low = (u32)(tsc >> rdtsc_bitshift);
-    delta_tsc = (s32)(low - stime_pcc);
+    delta_tsc = (s32)(low - tsc_irq);
     if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
     delta = ((u64)delta_tsc * st_scale_f);
     delta >>= 32;
     delta += ((u64)delta_tsc * st_scale_i);
 
-    return stime_now + delta;
+    return stime_irq + delta;
 }
 
 s_time_t get_s_time(void)
@@ -303,25 +291,23 @@ s_time_t get_s_time(void)
 }
 
 
-/* Wall Clock time */
-struct timeval    wall_clock_time; /* wall clock time at last update */
-s_time_t          wctime_st;       /* system time at last update */
-
 void do_gettimeofday(struct timeval *tv)
 {
     unsigned long flags;
     unsigned long usec, sec;
 
     spin_lock_irqsave(&stime_lock, flags);
-    usec = ((unsigned long)(__get_s_time() - wctime_st))/1000;
+    usec = ((unsigned long)(__get_s_time() - stime_irq))/1000;
     sec = wall_clock_time.tv_sec;
     usec += wall_clock_time.tv_usec;
     spin_unlock_irqrestore(&stime_lock, flags);
 
-    while (usec >= 1000000) {
+    while ( usec >= 1000000 ) 
+    {
         usec -= 1000000;
         sec++;
     }
+
     tv->tv_sec = sec;
     tv->tv_usec = usec;
 }
@@ -331,11 +317,11 @@ void do_settimeofday(struct timeval *tv)
     printk("XXX: do_settimeofday not implemented\n");
 }
 
+
 /***************************************************************************
  * Update times
  ***************************************************************************/
 
-/* update a domains notion of time */
 void update_dom_time(shared_info_t *si)
 {
     unsigned long flags;
@@ -343,15 +329,13 @@ void update_dom_time(shared_info_t *si)
     spin_lock_irqsave(&stime_lock, flags);
     si->cpu_freq       = cpu_freq;
     si->rdtsc_bitshift = rdtsc_bitshift;
-    si->system_time    = stime_now;
-    si->st_timestamp   = stime_pcc;
+    si->system_time    = stime_irq;
+    si->st_timestamp   = tsc_irq;
     si->tv_sec         = wall_clock_time.tv_sec;
     si->tv_usec        = wall_clock_time.tv_usec;
-    si->wc_timestamp   = wctime_st;
+    si->wc_timestamp   = stime_irq;
     si->wc_version++;
     spin_unlock_irqrestore(&stime_lock, flags);
-
-    TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st));
 }
 
 /*
@@ -362,21 +346,12 @@ void update_dom_time(shared_info_t *si)
  * - index 0 -> go slower
  * - index 1 -> frequency as determined during calibration
  * - index 2 -> go faster
- */
-/*
- * NB. The period is not a whole number of seconds since we want to avoid
- * being in sync with the CMOS update-in-progress flag, which causes this
- * routine to bail.
- */
-/*
+ * 
  * NB2. Note that update_scale is called from update_time with the stime_lock
  * still held. This is because we must only slow down cpu_freq at a timebase
  * change. If we did it in the middle of an update period then time would
  * seem to jump backwards since BASE+OLD_FREQ*DIFF > BASE+NEW_FREQ*DIFF.
  */
-#define SCALE_UPDATE_PERIOD   MILLISECS(50200)
-static unsigned long   init_cmos_time;
-static u64             cpu_freqs[3];
 static void update_scale(void)
 {
     unsigned long  cmos_time;
@@ -389,15 +364,18 @@ static void update_scale(void)
         return;
 
     ct = (u32)(cmos_time - init_cmos_time);
-    st = (u32)(stime_now/SECONDS(1));
+    st = (u32)(stime_irq/SECONDS(1));
     dt = (s32)(ct - st);
 
-    /* work out adjustment to scaling factor. allow +/- 1s drift */
-    if (dt < -1) freq_index = 0;       /* go slower */
-    else if (dt > 1) freq_index = 2;   /* go faster */
-    else freq_index = 1;               /* correct speed */
+    /* Work out adjustment to scaling factor. Allow +/- 1s drift. */
+    if ( dt < -1 ) 
+        freq_index = 0;   /* go slower */
+    else if ( dt > 1 ) 
+        freq_index = 2;   /* go faster */
+    else 
+        freq_index = 1;   /* correct speed */
 
-    if ((dt <= -10) || (dt >= 10))
+    if ( (dt <= -10) || (dt >= 10) )
         printk("Large time drift (cmos time - system time = %ds)\n", dt);
 
     /* set new frequency  */
@@ -411,36 +389,32 @@ static void update_scale(void)
 }
 
 
-/*
- * Update hypervisors notion of time
- * This is done periodically of it's own timer
- */
-#define TIME_UPDATE_PERIOD    MILLISECS(200)
-static struct ac_timer update_timer;
-static void update_time(unsigned long foo)
+static void update_time(unsigned long unused)
 {
     unsigned long  flags;
     s_time_t       new_st;
     unsigned long  usec;
-    u64            full_pcc;
+    u64            full_tsc;
     static int     calls_since_scale_update = 0;
 
     spin_lock_irqsave(&stime_lock, flags);
 
-    /* Update system time. */
-    stime_now = new_st = __get_s_time();
-    rdtscll(full_pcc);
-    stime_pcc = (u32)(full_pcc >> rdtsc_bitshift);
+    rdtscll(full_tsc);
+    new_st = __get_s_time();
 
     /* Update wall clock time. */
-    usec = ((unsigned long)(new_st - wctime_st))/1000;
+    usec = ((unsigned long)(new_st - stime_irq))/1000;
     usec += wall_clock_time.tv_usec;
-    while (usec >= 1000000) {
+    while ( usec >= 1000000 ) 
+    {
         usec -= 1000000;
         wall_clock_time.tv_sec++;
     }
     wall_clock_time.tv_usec = usec;
-    wctime_st = new_st;
+
+    /* Update system time. */
+    stime_irq = new_st;
+    tsc_irq   = (u32)(full_tsc >> rdtsc_bitshift);
 
     /* Maybe update our rate to be in sync with the RTC. */
     if ( ++calls_since_scale_update >= 
@@ -452,8 +426,8 @@ static void update_time(unsigned long foo)
 
     spin_unlock_irqrestore(&stime_lock, flags);
 
-    TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n",
-               smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec,
+    TRC(printk("TIME[%02d] update time: stime_irq=%lld now=%lld,wct=%ld:%ld\n",
+               smp_processor_id(), stime_irq, new_st, wall_clock_time.tv_sec,
                wall_clock_time.tv_usec));
 
     /* Reload the timer. */
@@ -462,17 +436,12 @@ static void update_time(unsigned long foo)
 }
 
 
-/***************************************************************************
- * Init Xeno Time
- * This has to be done after all CPUs have been booted
- ***************************************************************************/
+/* Late init function (after all CPUs are booted). */
 int __init init_xeno_time()
 {
-    int      cpu = smp_processor_id();
-    u32      cpu_cycle;  /* time of one cpu cyle in pico-seconds */
-    u64      scale;      /* scale factor */
+    u64      scale;
     s64      freq_off;
-    u64      full_pcc;
+    u64      full_tsc;
     unsigned int cpu_ghz;
 
     spin_lock_init(&stime_lock);
@@ -481,61 +450,47 @@ int __init init_xeno_time()
     for ( rdtsc_bitshift = 0; cpu_ghz != 0; rdtsc_bitshift++, cpu_ghz >>= 1 )
         continue;
 
-    printk("Init Time[%02d]: %u\n", cpu, rdtsc_bitshift);
-
-    /* System Time */
-    cpu_cycle   = (u32) (1000000000LL/cpu_khz); /* in pico seconds */
-
-    /* calculate adjusted frequencies */
-    freq_off  = cpu_freq/1000; /* .1%  */
+    /* Calculate adjusted frequencies: +/- 0.1% */
+    freq_off = cpu_freq/1000;
     cpu_freqs[0] = cpu_freq + freq_off;
     cpu_freqs[1] = cpu_freq;
     cpu_freqs[2] = cpu_freq - freq_off;
 
-    scale = 1000000000LL << (32 + rdtsc_bitshift);
+    scale  = 1000000000LL << (32 + rdtsc_bitshift);
     scale /= cpu_freq;
     st_scale_f = scale & 0xffffffff;
     st_scale_i = scale >> 32;
 
-    /* Wall Clock time */
-    wall_clock_time.tv_sec  = get_cmos_time();
-    wall_clock_time.tv_usec = 0;
-
-    /* init cmos_time for synchronising */
-    init_cmos_time = wall_clock_time.tv_sec;
+    /* System time ticks from zero. */
+    rdtscll(full_tsc);
+    stime_irq = (s_time_t)0;
+    tsc_irq   = (u32)(full_tsc >> rdtsc_bitshift);
 
-    /* set starting times */
-    stime_now = (s_time_t)0;
-    rdtscll(full_pcc);
-    stime_pcc = (u32)(full_pcc >> rdtsc_bitshift);
-    wctime_st = NOW();
+    /* Wallclock time starts as the initial RTC time. */
+    wall_clock_time.tv_sec  = init_cmos_time = get_cmos_time();
+    wall_clock_time.tv_usec = 0;
 
-    /* start timer to update time periodically */
+    /* Start timer to periodically update time and frequency scale. */
     init_ac_timer(&update_timer, 0);
     update_timer.data = 1;
     update_timer.function = &update_time;
     update_time(0);
  
-    printk(".... System Time: %lldns\n",   NOW());
-    printk(".....cpu_freq:    %08X%08X\n", (u32)(cpu_freq>>32), (u32)cpu_freq);
-    printk(".....cpu_cycle:   %u ps\n",    cpu_cycle);
-    printk(".....scale:       %08X%08X\n", (u32)(scale>>32), (u32)scale);
-    printk(".... st_scale_f:  %X\n",       st_scale_f);
-    printk(".... st_scale_i:  %X\n",       st_scale_i);
-    printk(".... stime_pcc:   %u\n",       stime_pcc);
-
-    printk(".... Wall Clock:  %lds %ldus\n", wall_clock_time.tv_sec,
-           wall_clock_time.tv_usec);
-    printk(".... wctime_st:   %lld\n", wctime_st);
+    printk("Time init:\n");
+    printk(".... System Time: %lldns\n", 
+           NOW());
+    printk(".... cpu_freq:    %08X:%08X\n", 
+           (u32)(cpu_freq>>32), (u32)cpu_freq);
+    printk(".... scale:       %08X:%08X\n", 
+           (u32)(scale>>32), (u32)scale);
+    printk(".... Wall Clock:  %lds %ldus\n", 
+           wall_clock_time.tv_sec, wall_clock_time.tv_usec);
 
     return 0;
 }
 
 
-/***************************************************************************
- * Init
- ***************************************************************************/
-
+/* Early init function. */
 void __init time_init(void)
 {
     unsigned long ticks_per_frac = calibrate_tsc();
index 1e5d3f6bcd587008e5ec211d630f7b9260c386ed..a34d8f12c7a0e17a67438e0718e58aad80843b97 100644 (file)
@@ -1,20 +1,15 @@
 /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
  ****************************************************************************
- * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2002-2003 University of Cambridge
  ****************************************************************************
  *
  *        File: ac_timer.c
  *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- *     Changes: 
+ *              Keir Fraser (kaf24@cl.cam.ac.uk)
  *              
- *        Date: Nov 2002
- * 
  * Environment: Xen Hypervisor
  * Description: Accurate timer for the Hypervisor
- *
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
- ****************************************************************************
  */
 
 #include <xeno/config.h>
 #define TRC(_x)
 #endif
 
-/*****************************************************************************
+/*
  * We pull handlers off the timer list this far in future,
  * rather than reprogramming the time hardware.
- *****************************************************************************/
+ */
 #define TIMER_SLOP (50*1000) /* ns */
 
 /* A timer list per CPU */
@@ -65,24 +60,29 @@ static inline unsigned long __add_ac_timer(struct ac_timer *timer)
     /*
      * Add timer to the list. If it gets added to the front we schedule
      * a softirq. This will reprogram the timer, or handle the timer event
-     * imemdiately, depending on whether alarm is sufficiently ahead in the
+     * immediately, depending on whether alarm is sufficiently ahead in the
      * future.
      */
-    if (list_empty(&ac_timers[cpu].timers)) {
+    if ( list_empty(&ac_timers[cpu].timers) )
+    {
         list_add(&timer->timer_list, &ac_timers[cpu].timers);
         goto send_softirq;
-    } else {
+    } 
+    else 
+    {
         struct list_head *pos;
         struct ac_timer  *t;
 
-        list_for_each(pos, &ac_timers[cpu].timers) {
+        list_for_each ( pos, &ac_timers[cpu].timers )
+        {
             t = list_entry(pos, struct ac_timer, timer_list);
-            if (t->expires > timer->expires)
+            if ( t->expires > timer->expires )
                 break;
         }
+
         list_add(&(timer->timer_list), pos->prev);
 
-        if (timer->timer_list.prev == &ac_timers[cpu].timers)
+        if ( timer->timer_list.prev == &ac_timers[cpu].timers )
             goto send_softirq;
     }
 
@@ -104,7 +104,8 @@ void add_ac_timer(struct ac_timer *timer)
     cpu_mask = __add_ac_timer(timer);
     spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
 
-    if ( cpu_mask ) smp_send_event_check_mask(cpu_mask);
+    if ( cpu_mask ) 
+        smp_send_event_check_mask(cpu_mask);
 }
 
 
@@ -135,11 +136,15 @@ static inline unsigned long __rem_ac_timer(struct ac_timer *timer)
 
     detach_ac_timer(timer);
     
-    if (timer->timer_list.prev == &ac_timers[cpu].timers) {
+    if ( timer->timer_list.prev == &ac_timers[cpu].timers ) 
+    {
         /* just removed the head */
-        if (list_empty(&ac_timers[cpu].timers)) {
+        if ( list_empty(&ac_timers[cpu].timers) ) 
+        {
             goto send_softirq;
-        } else {
+        } 
+        else 
+        {
             timer = list_entry(ac_timers[cpu].timers.next,
                                struct ac_timer, timer_list);
             if ( timer->expires > (NOW() + TIMER_SLOP) )
@@ -165,7 +170,8 @@ void rem_ac_timer(struct ac_timer *timer)
         cpu_mask = __rem_ac_timer(timer);
     spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
 
-    if ( cpu_mask ) smp_send_event_check_mask(cpu_mask);
+    if ( cpu_mask ) 
+        smp_send_event_check_mask(cpu_mask);
 }
 
 
@@ -192,7 +198,8 @@ void mod_ac_timer(struct ac_timer *timer, s_time_t new_time)
 
     spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
 
-    if ( cpu_mask ) smp_send_event_check_mask(cpu_mask);
+    if ( cpu_mask ) 
+        smp_send_event_check_mask(cpu_mask);
 }
 
 
@@ -214,25 +221,31 @@ void do_ac_timer(void)
     TRC(printk("ACT  [%02d] do(): now=%lld\n", cpu, NOW()));
         
     /* Sanity: is the timer list empty? */
-    if ( list_empty(&ac_timers[cpu].timers) ) goto out;
+    if ( list_empty(&ac_timers[cpu].timers) ) 
+        goto out;
 
     /* Handle all timeouts in the near future. */
     while ( !list_empty(&ac_timers[cpu].timers) )
     {
         t = list_entry(ac_timers[cpu].timers.next,struct ac_timer, timer_list);
-        if ( t->expires > (NOW() + TIMER_SLOP) ) break;
+        if ( t->expires > (NOW() + TIMER_SLOP) ) 
+            break;
 
         ASSERT(t->cpu == cpu);
 
-        /* do some stats */
+        /* Do some stats collection. */
         diff = (now - t->expires);
-        if (diff > 0x7fffffff) diff =  0x7fffffff; /* THIS IS BAD! */
+        if ( diff > 0x7fffffff ) 
+            diff =  0x7fffffff; /* THIS IS BAD! */
         max = perfc_valuea(ac_timer_max, cpu);
-        if (diff > max) perfc_seta(ac_timer_max, cpu, diff);
+        if ( diff > max ) 
+            perfc_seta(ac_timer_max, cpu, diff);
 
         detach_ac_timer(t);
+
         spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
-        if ( t->function != NULL ) t->function(t->data);
+        if ( t->function != NULL ) 
+            t->function(t->data);
         spin_lock_irqsave(&ac_timers[cpu].lock, flags);
     }
         
@@ -246,7 +259,9 @@ void do_ac_timer(void)
             TRC(printk("ACT  [%02d] do(): again\n", cpu));
             goto do_timer_again;
         }
-    } else {
+    } 
+    else 
+    {
         reprogram_ac_timer((s_time_t) 0);
     }
 
@@ -288,10 +303,7 @@ static void ac_timer_softirq_action(struct softirq_action *a)
     }
 }
 
-/*****************************************************************************
- * debug dump_queue
- * arguments: queue head, name of queue
- *****************************************************************************/
+
 static void dump_tqueue(struct list_head *queue, char *name)
 {
     struct list_head *list;
@@ -300,7 +312,9 @@ static void dump_tqueue(struct list_head *queue, char *name)
 
     printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
             (unsigned long) queue->next, (unsigned long) queue->prev);
-    list_for_each (list, queue) {
+
+    list_for_each ( list, queue ) 
+    {
         t = list_entry(list, struct ac_timer, timer_list);
         printk ("  %s %d : %lx ex=0x%08X%08X %lu  n: %lx, p: %lx\n",
                 name, loop++, 
@@ -308,10 +322,10 @@ static void dump_tqueue(struct list_head *queue, char *name)
                 (u32)(t->expires>>32), (u32)t->expires, t->data,
                 (unsigned long)list->next, (unsigned long)list->prev);
     }
-    return; 
 }
 
-void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
+
+static void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
 {
     u_long   flags; 
     s_time_t now = NOW();
@@ -319,14 +333,15 @@ void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
 
     printk("Dumping ac_timer queues: NOW=0x%08X%08X\n",
            (u32)(now>>32), (u32)now); 
-    for (i = 0; i < smp_num_cpus; i++) {
+
+    for ( i = 0; i < smp_num_cpus; i++ )
+    {
         printk("CPU[%02d] ", i);
         spin_lock_irqsave(&ac_timers[i].lock, flags);
         dump_tqueue(&ac_timers[i].timers, "ac_time"); 
         spin_unlock_irqrestore(&ac_timers[i].lock, flags);
         printk("\n");
     }
-    return; 
 }
 
 
@@ -343,52 +358,6 @@ void __init ac_timer_init(void)
         INIT_LIST_HEAD(&ac_timers[i].timers);
         spin_lock_init(&ac_timers[i].lock);
     }
-}
-
 
-/*****************************************************************************
- * GRAVEYARD
- *****************************************************************************/
-
-#if 0
-
-#ifdef AC_TIMER_STATS
-#define BUCKETS     1000
-#define MAX_STATS
-typedef struct act_stats_st
-{
-    u32 count;
-    u32 times[2*(BUCKETS)];
-} __cacheline_aligned act_stats_t;
-static act_stats_t act_stats[NR_CPUS];
-
-#endif
-
-#ifdef AC_TIMER_STATS
-    {
-        XXX this is at the wrong place
-        s32 diff;
-        u32 i;
-        diff = ((s32)(NOW() - t->expires)) / 1000; /* delta in us */
-        if (diff < -BUCKETS)
-            diff = -BUCKETS;
-        else if (diff > BUCKETS)
-            diff = BUCKETS;
-        act_stats[cpu].times[diff+BUCKETS]++;
-        act_stats[cpu].count++;
-
-        if (act_stats[cpu].count >= 5000) {
-            printk("ACT Stats\n");
-            for (i=0; i < 2*BUCKETS; i++) {
-                if (act_stats[cpu].times[i] != 0)
-                    printk("ACT [%02d]: %3dus: %5d\n",
-                           cpu,i-BUCKETS, act_stats[cpu].times[i]);
-                act_stats[cpu].times[i]=0;
-            }
-            act_stats[cpu].count = 0;
-            printk("\n");
-        }
-    }
-#endif
-
-#endif /* 0 */
+    add_key_handler('a', dump_timerq, "dump ac_timer queues");
+}
index 261e6fbb7952658c364ca731c5eb21e26a574709..b3d3631777cf7cb8ff550b48092b1c5946a44d2b 100644 (file)
@@ -116,7 +116,6 @@ void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs)
 
 extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs);
 extern void perfc_reset (u_char key, void *dev_id, struct pt_regs *regs);
-extern void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs);
 extern void dump_runq(u_char key, void *dev_id, struct pt_regs *regs);
 extern void print_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
 extern void reset_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
@@ -131,7 +130,6 @@ void initialize_keytable()
        key_table[i].handler = (key_handler *)NULL; 
        
     /* setup own handlers */
-    add_key_handler('a', dump_timerq,    "dump ac_timer queues");
     add_key_handler('d', dump_registers, "dump registers"); 
     add_key_handler('h', show_handlers, "show this message");
     add_key_handler('l', print_sched_histo, "print sched latency histogram");
index 9c9ae871824e765005362e71cb7c684be25c5368..40145ddb0f39104bbb352507222c389464d62e50 100644 (file)
@@ -5,16 +5,9 @@
  *
  *        File: time.h
  *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- *     Changes: 
- *              
- *        Date: Nov 2002
  * 
  * Environment: Xen Hypervisor
  * Description: Architecture dependent definition of time variables
- *
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
  */
 
 #ifndef _ASM_TIME_H_
 #include <asm/types.h>
 #include <asm/msr.h>
 
-/*
- * Cycle Counter Time
- */
-typedef u64 cc_time_t;
-static inline cc_time_t get_cc_time()
-{
-       u64 ret;
-       rdtscll(ret);
-       return ret;
-}
-
-/*
- * System Time
- */
-typedef s64      s_time_t;          /* System time */
-extern  u32      stime_pcc;      /* cycle counter value at last timer irq */
-extern  s_time_t stime_now;      /* time in ns at last timer IRQ */
-
-/*
- * Domain Virtual Time
- */
-typedef u64 dv_time_t;
+typedef s64 s_time_t;  /* system time */
 
 extern int using_apic_timer;